/*
 * Copyright (c) zhg2yqq.com Corp.
 * All Rights Reserved.
 */
package com.zhg2yqq.wheels.security.handler;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import com.alibaba.fastjson2.JSON;
import com.zhg2yqq.wheels.common.response.RestResponse;
import com.zhg2yqq.wheels.common.util.ServletUtils;
import com.zhg2yqq.wheels.security.CustomeSecurityProperties;
import com.zhg2yqq.wheels.security.ISecurityEventHook;
import com.zhg2yqq.wheels.security.ISecurityRepository;
import com.zhg2yqq.wheels.security.SecurityRepositoryHelper;
import com.zhg2yqq.wheels.security.context.SecurityLoginUser;
import com.zhg2yqq.wheels.security.context.SecurityUserHolder;

/**
 * @author zhg2yqq, 2022年11月28日
 * @version zhg2yqq v1.0
 */
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    private Logger log = LoggerFactory.getLogger(LoginSuccessHandler.class);

    private ISecurityEventHook eventHook;
    private ISecurityRepository securityRepository;
    private CustomeSecurityProperties securityProperties;

    public LoginSuccessHandler(CustomeSecurityProperties securityProperties,
                               ISecurityRepository securityRepository) {
        this.securityProperties = securityProperties;
        this.securityRepository = securityRepository;
    }

    public LoginSuccessHandler(CustomeSecurityProperties securityProperties,
                               ISecurityRepository securityRepository, ISecurityEventHook eventHook) {
        this.securityProperties = securityProperties;
        this.securityRepository = securityRepository;
        this.eventHook = eventHook;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication)
            throws IOException, ServletException {
        if (eventHook != null) {
            eventHook.loginSuccessEvent(SecurityUserHolder.getUser(), request);
        }

        if (authentication.getPrincipal() instanceof SecurityLoginUser) {
            // 保存认证信息
            String token = securityRepository.saveLoginUser(request, response, authentication);

            sendAuthorization(response, token);
            if (ServletUtils.isAjaxRequest(request)) {
                // 允许跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                // 允许自定义请求头token(允许head跨域)
                response.setHeader("Access-Control-Allow-Headers",
                        "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
                response.setContentType("application/json;charset=UTF-8");

                TokenType tokenType = new TokenType();
                tokenType.setAccessToken(token);
                response.getWriter().write(JSON.toJSONString(RestResponse.success(tokenType)));
            }
        }

        if (securityProperties.getLogoutAfterUrl() != null && !ServletUtils.isAjaxRequest(request)) {
            response.sendRedirect(securityProperties.getLoginAfterUrl());
        }
        log.info("用户{}登陆成功", authentication.getName());
    }

    private void sendAuthorization(HttpServletResponse response, String token) {
        String tokenName = securityProperties.getTokenName();
        response.setHeader(tokenName, SecurityRepositoryHelper.HEADER_TOKEN_PREFIX + token);
        try {
            Cookie cookie = new Cookie(tokenName,
                    URLEncoder.encode(token, StandardCharsets.UTF_8.toString()));
            cookie.setMaxAge(-1);
            cookie.setPath("/");
            cookie.setHttpOnly(true);
            response.addCookie(cookie);
        } catch (UnsupportedEncodingException e1) {

        }
    }

    static class TokenType {
        private String id; // 编号
        private String accessToken; // 访问令牌
        private String refreshToken; // 刷新令牌
        private String userId; // 用户编号
        private String userType; //用户类型
        private String clientId; //客户端编号
        private Long expiresTime; //过期时间

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getAccessToken() {
            return accessToken;
        }

        public void setAccessToken(String accessToken) {
            this.accessToken = accessToken;
        }

        public String getRefreshToken() {
            return refreshToken;
        }

        public void setRefreshToken(String refreshToken) {
            this.refreshToken = refreshToken;
        }

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        public String getUserType() {
            return userType;
        }

        public void setUserType(String userType) {
            this.userType = userType;
        }

        public String getClientId() {
            return clientId;
        }

        public void setClientId(String clientId) {
            this.clientId = clientId;
        }

        public Long getExpiresTime() {
            return expiresTime;
        }

        public void setExpiresTime(Long expiresTime) {
            this.expiresTime = expiresTime;
        }
    }
}
